<?php
/**
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 */

//TODO: написать обработчик ошибок

class Files
{
	const SYSTEM_UPLOAD_DIRS_PERM = 0755;
	
	/**
	 * 
	 */
	const UPLOAD_PATH = '/img/tmp/uploads';
	
	/**
	 * 
	 */
	const DEFAULT_KEY = 'Filedata';
	
	/**
	 * 
	 */
	protected $_module = '';
	
	/**
	 * 
	 */
	protected $_owner = '';
	
	/**
	 * 
	 */
	protected $_filetype = '';

	/**
	 * 
	 */
	protected $_filename = '';
		
	/**
	 * 
	 */
	protected $_folder = '';
	
	/**
	 * 
	 */
	protected $_upload_path = '';
	
	/**
	 * 
	 */
	public function __construct()
	{
	}
	
	/**
	 * 
	 */
	public function getPreparedOwner( $owner )
	{
		return $this->_prepareOwner( $owner );
	}
	
	/**
	 * 
	 */
	public function getPreparedFolder( $folder )
	{
		return $this->_prepareFolder( $folder );
	}	
	
	/**
	 * 
	 */
	public function getFileExtension( $filename='' )
	{
		if ( empty( $filename ) )
			$filename = $this->getFileRealName();
			
		if ( !empty( $filename ) )
		{
			return mb_strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );
		}
		
		return false;
	}
	
	/**
	 * 
	 */
	public function getFileRealName( $key='' )
	{
		if ( empty( $key ) )
			$key = self::DEFAULT_KEY;
			
		return $_FILES[$key]['name'];		
	}
	
	/**
	 * 
	 */
	public function getFilePath( $owner )
	{
		return $this->_prepareOwner( $owner );
	}
	
	/**
	 * 
	 */
	public function getFullFilePath()
	{
		return SYSTEM_UPLOAD_DIR . $this->getModule() . '/' . $this->getFilePath( $this->getOwner() ) . '/' . $this->getFileName();
	}
	
	/**
	 * 
	 */
	public function downloadFile( $source, $name='' )
	{
		if ( empty( $name ) )
			$name = pathinfo( $source, PATHINFO_BASENAME );
		
        if ( is_file( $source ) )
        {
        	if ( is_readable( $source ) )
        	{
//        		Core_Helper::execute( array('Core_Logger', 'log'), array( 'download', 'file', $source ) );
        		
        		if( isset( $_SERVER["HTTP_X_NGINX_SCHEME"] ) )
        		{       			
			    	header("Content-type: application/octet-stream", true);
	    			header("Content-Disposition: attachment; filename=" . str_replace(' ', '-', $name));
	    			header("X-Accel-Redirect: /" . str_replace( SYSTEM_HTDOCS_DIR, '', $source ));
	    			exit;
        		}
        		else
        		{
		        	header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // some day in the past
	        		header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
	        		header("Content-type: application/x-download");
	        		header("Content-Disposition: attachment; filename=" . str_replace(' ', '-', $name));
	        		header("Content-Transfer-Encoding: binary");
	        		readfile( $source );
	        		exit;
        		}
        	}
        	else
        	{
        		//$this->error = 'msg_file_unreadable';
        	}
        }
        else
        {
        	//$this->error = 'msg_file_missed';
        }
		
	}
		
	/**
	 * 
	 */
	public function setModule( $module )
	{
		if ( !empty( $module ) )
			$this->_module = $module;
	}
	
	/**
	 * 
	 */
	public function getModule()
	{
		return $this->_module;
	}
		
	/**
	 * 
	 */
	public function setOwner( $owner )
	{
		if ( !empty( $owner ) )
			$this->_owner = $this->_prepareOwner( $owner );
	}
	
	/**
	 * 
	 */
	public function getOwner()
	{
		return $this->_owner;
	}
	
	/**
	 * 
	 */
	public function setFileType( $filetype )
	{
		if ( !empty( $filetype ) )
			$this->_filetype = $filetype;
	}
	
	/**
	 * 
	 */
	public function setFileName( $filename )
	{
		if ( !empty( $filename ) )
			$this->_filename = $filename;
	}	
	
	/**
	 * 
	 */
	public function getFileName()
	{
		return $this->_filename;
	}
	
	/**
	 * 
	 */
	public function setFolder( $folder )
	{
		if ( !empty( $folder ) )
			$this->_folder = $this->_prepareFolder( $folder );
	}
	
	/**
	 * 
	 */
	public function copyFile( $from, $to )
	{
		if ( !empty( $from ) && !empty( $to ) )
		{
			return copy( $from, $to );
		}
		
		return false;
	}
	
	/**
	 * 
	 */
	public function copyFileFromUrl( $from, $to )
	{
		if ( !empty( $from ) && !empty( $to ) )
		{
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_HEADER, 0);
			curl_setopt( $ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" );
			curl_setopt( $ch, CURLOPT_URL, $from );
			curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
			curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
			curl_setopt( $ch, CURLOPT_AUTOREFERER, true );
			curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
			curl_setopt( $ch, CURLOPT_MAXREDIRS, 10 );
			$data = curl_exec( $ch );
			curl_close($ch);
			
			$fh = fopen( $to, 'wb');
			flock($fh, LOCK_EX);
			fwrite( $fh, $data ); 
			flock($fh, LOCK_UN);
			fclose($fh);

			return true;
		}
		
		return false;
	}
	
	/**
	 * 
	 */
	public function uploadFile( $key='', $path='' )
	{
		if ( empty( $key ) )
			$key = self::DEFAULT_KEY;
			
		if ( $_FILES[$key]['size'] > 0 )
		{
			$ext = mb_strtolower( pathinfo( $_FILES[$key]['name'], PATHINFO_EXTENSION ) );
			$this->_filename .= '.' . $ext;
			
			$upload_path = $path . $this->_filename;
			
			if ( move_uploaded_file( $_FILES[$key]['tmp_name'], $upload_path) )
			{
				chmod( $upload_path, SYSTEM_UPLOAD_FILES_PERM );
				
//				Core_Helper::execute( array('Core_Logger', 'log'), array( 'upload', null, $upload_path ) );
				
				return $upload_path;
			}
		}
	}
	
	/**
	 * 
	 */
	public function uploadFileStream( $path='' )
	{
		$headers = array();
		$file_request = isset( $_FILES['file'] ) ? $_FILES['file'] : null;
		$uploaded_file = $file_request ? $file_request['tmp_name'] : null;
		
		$file = array();
		$file['name'] = basename( isset($headers['X-File-Name'] ) ? $headers['X-File-Name'] : $file_request['name'] );
		$file['type'] = isset( $headers['X-File-Type'] ) ? $headers['X-File-Type'] : $file_request['type'];
		$file['size'] = intval( isset( $headers['X-File-Size'] ) ? $headers['X-File-Size'] : $file_request['size'] );
		
		if ( $file['name'] )
		{
			$file_path = $path . $file['name'];
			$append_file = is_file( $file_path ) && $file['size'] > filesize( $file_path );
			clearstatcache();
			
			if ( $uploaded_file && is_uploaded_file( $uploaded_file ) )
			{
				if ( $append_file )
				{
					file_put_contents(
						$file_path,
						fopen( $uploaded_file, 'r' ),
						FILE_APPEND
					);
				}
				else
				{
					move_uploaded_file( $uploaded_file, $file_path );
				}
			}
			else
			{
				file_put_contents(
					$file_path,
					fopen('php://input', 'r'),
					$append_file ? FILE_APPEND : 0
				);
			}
			$file['size'] = filesize( $file_path );
			
			return $file;
		}
		
		return false;
	}
	
	/**
	 * 
	 */
	public function deleteFile( $file )
	{
		if ( is_readable( $file ) )
			return unlink( $file );
		
		return false;
	}
	
	/**
	 * 
	 */
	public function deleteFileByMask( $path, $mask )
	{
		if ( !empty( $path ) && !empty( $mask ) )
		{
			if ( is_dir( $path ) )
			{
				chdir( $path );
			
				foreach ( glob('*'.$mask.'*') as $filename )
				{					
					$this->deleteFile( $path . $filename );
				}
			
//				Core_Helper::execute( array('Core_Logger', 'log'), array( 'delete', 'file', $path . $mask ) );
				
				chdir( '..' );
			}			
		}
	}
	
	/**
	 * 
	 */
	public function deleteDirectory( $path, $dirs = '' )
	{
		if ( is_dir( $path ) )
		{
			chdir( $path );
		
			foreach ( glob('*.*') as $filename )
			{
				$this->deleteFile( rtrim( $path, '/' ) . '/' . $filename );
			}
			
			chdir('..');
			
//			Core_Helper::execute( array('Core_Logger', 'log'), array( 'delete', 'dir', $path ) );
			
			return @rmdir($path);
		}

        return false;
	}
	
	public function removeDir($dir)
	{ 
		if (is_dir($dir))
		{ 
			$objects = scandir($dir); 
			foreach ($objects as $object)
			{ 
				if ($object != "." && $object != "..") { 
					if (filetype($dir."/".$object) == "dir") $this->removeDir($dir."/".$object); else unlink($dir."/".$object); 
				} 
			}
			reset($objects); 
			rmdir($dir); 
		}
	}

    /**
     * Create recursive directories by path
     */
    public function createDir($path)
    {
        if(!is_dir($path))
            return mkdir($path, 0755, true);

        return false;
    }

	
	/**
	 * 
	 */
	public function createDirectory( $path='', $dirs='' )
	{
		if ( !empty( $path ) && !empty( $dirs ) )
		{
			$this->_createPath( $path, $dirs );
		}
		else
		{
			$this->_getUploadPath();
			$this->_createPath();
		}
	}
	
	/**
	 * Create recursive directories by path
	 */
	public function createDirectories( $path )
	{
		if($path)
			return mkdir($path, self::SYSTEM_UPLOAD_DIRS_PERM, true);
		
		return false;
	}
	
	public function createFile( $filename, $data = '', $fileMode = 'w+' )
	{
		$h = fopen($filename, $fileMode);
		
		if( flock($h, LOCK_EX) )
		{
			fwrite($h, $data);
			flock($h, LOCK_UN);
		}
		
		fclose($h);
	}
	
	/**
	 * 
	 */
	protected function _getUploadPath()
	{
		if ( !empty( $this->_module ) && !empty( $this->_owner ) )
		{
			$this->_upload_path = $this->_module . '/' .  $this->_owner . '/';
			
			if ( !empty( $this->_filetype) )
			{
				$this->_upload_path .= $this->_filetype . '/';
			} 
			
			if ( !empty( $this->_folder ) )
			{
				$this->_upload_path .= $this->_folder . '/'; 
			}
			
			return true;
		}
		
		return false;
	}
	
	/**
	 * 
	 */
	protected function _createPath( $path='', $dirs='' )
	{
		if ( empty( $path ) )
			$path = PUBLIC_PATH . self::UPLOAD_PATH;
			
//		if ( empty( $dirs ) )
//			$dirs = explode('/', $this->_upload_path);
//		else
//			$dirs = explode('/', $dirs);
		
//		Core_Helper::execute( array('Core_Logger', 'log'), array( 'create', 'dir', $path ) );
//		echo $path.$dirs; exit;
		if( !is_dir( $path . $dirs ) )
			return mkdir($path . $dirs, self::SYSTEM_UPLOAD_DIRS_PERM, true);
		
		return false;
		
//		return true;
		
//		foreach ( $dirs as $dir )
//		{
//			if( !is_dir( $path . $dir ) )
//				mkdir($path . $dir, self::SYSTEM_UPLOAD_DIRS_PERM);
//
//			$path .= $dir . '/';
//		}
//		
//		return true;
	}
	
	public function getRandomFolder( $id = '' )
	{
		if( !$id )
			$id = time();
		
		$md5 = md5($id . '/' . time());
		
		$path = '';

		$first_node = substr( $md5, -3, 3 );
		$second_node = substr( $md5, -7, 4 );

		$path = $first_node . '/' . $second_node . '/' . $md5 . '/';

		return $path;
	}
	
	/**
	 * 
	 */
	protected function _prepareOwner( $owner )
	{
        $owner = sprintf("%06s", $owner);
    	$owner = wordwrap($owner, 3, '/', 1);
        
        return $owner;
	}
	
	/**
	 * 
	 */
	protected function _prepareFolder( $folder )
	{
		return 'f' . $folder;
	}	
} 
 